#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <QMainWindow>
#include <QPushButton>
#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QWebSocket>
#include <QJsonObject>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QByteArray>
#include <QMapIterator>
#include <QScrollBar>
#include <QJsonArray>
#include <QTimer>
#include <QFileDialog>
#include <QDir>
#include <QFile>
#include <QImage>
#include <QBuffer>
#include <QHBoxLayout>
#include <QListWidgetItem>
#include "AddFriend.h"
#include "FriendListView.h"
#include "ChatListView.h"
#include "PhotoViewer.h"
#include "Register.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class Controller;
}
QT_END_NAMESPACE

class Controller : public QMainWindow
{
    Q_OBJECT

public:

    // 个人信息结构体(都带有缺省值)
    struct Info{
        QString id = "";// 账号
        QString pwd = "";// 密码
        QString nickname = "";// 昵称
        QString signature = "";// 个性签名
        QString gender = "";// 性别
        QPixmap avatarPixmap = QPixmap(":/images/login/defult_avatar.png");// 默认头像
        QString question = "";// 密保问题
        QString answer = "";// 密保答案
    };

    // 消息类型结构体
    enum MsgType{
        text,
        photo,
        file
    };

    Controller(QString id,QWebSocket* socket,QWidget *parent = nullptr);
    ~Controller();
    void initUI();
    void initSQLiteDB();// 初始化本地轻量级数据库（存储聊天项和聊天记录到本地）
    void sendJsonToServer(QJsonObject& jsonObj);// 封装json数据包
    void changeButtonImage(QPushButton* curBtn = nullptr);// 改变按钮选中状态的逻辑

    void askForMyInfo();// 初始时向服务端申请我的信息
    void askForMyFriendInfo();// 初始时向服务端申请好友信息
    void askForMyFriendRequestList();// 初始时向服务器申请好友申请列表信息
    void askForMyUnReadMsg();// 初始时向服务器申请未读消息信息
    void initChatData();// 初始时通过本地数据库获取聊天记录信息
    void initChatItem();// 初始时通过本地数据库获取聊天项信息

    void setMyPageEnable(bool flag);// 设置我的界面中的使能逻辑
    QPixmap byteArrayToPixmap(QString avatarStr);// 将字节数组转换为pixmap对象
    void addAChatItem(Info friendInfo,bool unread, QString lastMsg);// 添加一个聊天项(与聊天页面)
    void addAChatPage(QString id);// 添加一个聊天页面
    void addAFriendItem(Info friendInfo);// 添加一个新的好友项
    void addAFriendPage(Info friendInfo);// 创建一个以好友id命名的好友页面
    void liftSomeoneInChatView(QString id);// 在聊天项中提升某人到最前方
    void addAMsgIntoPage(const QWidget* page, const MsgType type, const QString &sender, QString& content, bool isInit, QString filename = "");// 向聊天页面增加一条消息
    void ifAddATimeLabel(QListWidget* listWidget, bool isInit);// 判断是否需要打印一条时间
    void createAChatMsg(QListWidget* listWidget,const QString &sender, const MsgType& type, const QString& content, QString filename = "");
    void addATimeLabel(QListWidget* listWidget, QDateTime& time);
    void updateAllTimeLabelWithDayChange();// 每一天更新聊天信息中的时间显示的逻辑

    // 接受来自服务端的通知
public:
    void dealMyInfo(const QJsonObject& jsonObj);// 初始时收到自己的个人信息
    void dealFriendInfo(const QJsonObject& jsonObj);// 初始化时收到所有的好友信息
    void dealFriendRequestList(const QJsonObject& jsonObj);// 初始化时收到所有好友的申请信息
    void dealMyUnReadMsg(const QJsonObject& jsonObj);// 初始化时收到所有的未读消息
    void dealChatItemList(const QJsonObject& jsonObj);// 初始化时收到的聊天项的信息
    void dealSearchFriendInfo(const QJsonObject& jsonObj);
    void dealAddFriendRequest(const QJsonObject& jsonObj);// 说明有别人添加我为好友的申请
    // 收到新朋友的个人信息,说明是自己的新朋友（创建聊天项、好友项等）
    void dealNewFriendInfo(const QJsonObject& jsonObj);
    void dealYouAreDelete(QString id);// 收到需要删除这个好友的通知
    void dealMsg(const QJsonObject& jsonObj);// 收到了一条消息
    void dealFriendCancel(QString friend_id);
    void dealDeleteAccount(const QJsonObject& jsonObj);
    void dealUpdateAFriendInfo(const QJsonObject& jsonObj);

public slots:
    void onDisconnected();// 断开连接了，重新登录
    void onTextMessageReceived(const QString &message);// 收到来自服务端的信息
    void onAskForFriendInfo(QString id);// 收到添加好友界面发来的信息查找请求（转发到服务端）
    void onAddFriendRequest(QString id);// 收到需要添加某人的请求（转发到服务端）
    void onFriendListViewIndexChange(const QModelIndex &current, const QModelIndex &previous);
    void onDeleteAFriend(QString id);// 收到需要删除某人的请求
    void onChatListViewIndexChange(const QModelIndex &current, const QModelIndex &previous);
    void onChatAvatarLabelClicked(QString id);// 聊天内部的头像被点击
    void onShowAPhoto(QPixmap pixmap);// 展示一张图片
    void onDownloadFile(QString filename, QString content);
    void onMenuChoice(QModelIndex index);

private slots:
    void on_chatBtn_clicked();// 聊天页面按钮被点击
    void on_friendBtn_clicked();// 好友页面按钮被点击
    void on_meBtn_clicked();// 我的页面被点击
    void on_settingBtn_clicked();// 设置页面被点击
    void on_exitAccountBtn_clicked();// 点击了退出账号按钮
    void on_deleteAccountBtn_clicked();// 点击了注销账号按钮
    void on_addFriendBtn_clicked();// 添加好友按钮被点击
    void on_sendBtn_clicked();// 点击了发送消息按钮
    void closeEvent(QCloseEvent* event) override;
    void on_imageBtn_clicked();// 点击了发送图片按钮
    void on_fileBtn_clicked();// 点击了发送文件按钮
    void on_editSavsBtn_clicked();// 在我的界面点击了修改按钮

signals:
    void goBackToLogin();// 向管理类发送退出账号的信号
    void friendInfo(const QJsonObject& jsonObj);// 查询到的某人的信息
    void deleteAFriend(QString id);// 删除某位好友的信号

private:
    Ui::Controller *ui;
    QString m_id;
    QWebSocket* m_socket;// 保存自身的套接字
    QSqlDatabase m_db;// 存储我的本地SQLite轻量级数据库
    Info m_info;// 存储我的个人信息
    QMap<QString,Info> m_friendMap;// 存储朋友的信息映射
    QStandardItemModel* m_friendModel;// 好友页面的模型
    QStandardItem* m_friendItem;// 保存好友页面第一项
    QVector<QString> m_friendRequestList;// 保存好友申请列表中的好友
    QStandardItemModel* m_chatModel;// 聊天页面的模型
};

#endif // CONTROLLER_H
